export default class Heart {
    private x: number = 0;
    private y: number = 0;
    private size: number = 0;
    private sizeChange: number = 0;
    private opacity: number = 0;
    private opacityChange: number = 0;
    private light: number = 0;
    private color: string = '';
    private readonly w: number;
    private readonly h: number = 0;
    private readonly ctx: any = '';
    private config = {
        sizeMin: 1,
        sizeMax: 2,
        sizeAddMin: 0.3,
        sizeAddMax: 0.5,
        opacityMin: 0.3,
        opacityMax: 0.5,
        opacityPrevMin: .003,
        opacityPreMax: .005,
        lightMin: 0,
        lightMax: 90,
    };

    public constructor(w: number, h: number, ctx: any,) {
        this.w = w;
        this.h = h;
        this.ctx = ctx;
        this.reset();
    }

    private get styleColor(): number {
        return this.findRandom(0, 360);
    }

    private findRandom(n1: number, n2: number) {
        return Math.random() * (n2 - n1) + n1;
    }

    private reset(): void {
        this.x = this.findRandom(0, this.w);
        this.y = this.findRandom(0, this.h);
        this.size = this.findRandom(this.config.sizeMin, this.config.sizeMax);
        this.sizeChange = this.findRandom(this.config.sizeAddMin, this.config.sizeAddMax);
        this.opacity = this.findRandom(this.config.opacityMin, this.config.opacityMax);
        this.opacityChange = this.findRandom(this.config.opacityPrevMin, this.config.opacityPreMax);
        this.light = this.findRandom(this.config.lightMin, this.config.lightMax);
        this.color = `hsl(${this.styleColor},100%,${this.light}%)`;
    }

    private run(): boolean {
        this.opacity -= this.opacityChange;
        this.size += this.sizeChange;
        if (this.opacity <= 0) {
            this.reset();
            return false;
        }
        this.ctx.fillStyle = this.color;
        this.ctx.globalAlpha = this.opacity;
        this.ctx.beginPath();
        this.draw(this.x, this.y, this.size, this.size);
        this.ctx.closePath();
        this.ctx.fill();
        this.ctx.globalAlpha = 1;
        return true;
    }

    private draw(x: number, y: number, z: number, m: number): void {
        y -= m * 10;
        this.ctx.moveTo(x, y);
        z *= 0.05;
        this.ctx.bezierCurveTo(x, y - 3 * z, x - 5 * z, y - 15 * z, x - 25 * z, y - 15 * z);
        this.ctx.bezierCurveTo(x - 55 * z, y - 15 * z, x - 55 * z, y + 22.5 * z, x - 55 * z, y + 22.5 * z);
        this.ctx.bezierCurveTo(x - 55 * z, y + 40 * z, x - 35 * z, y + 62 * z, x, y + 80 * z);
        this.ctx.bezierCurveTo(x + 35 * z, y + 62 * z, x + 55 * z, y + 40 * z, x + 55 * z, y + 22.5 * z);
        this.ctx.bezierCurveTo(x + 55 * z, y + 22.5 * z, x + 55 * z, y - 15 * z, x + 25 * z, y - 15 * z);
        this.ctx.bezierCurveTo(x + 10 * z, y - 15 * z, x, y - 3 * z, x, y);
    }
}